package com.strong.config.security.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.strong.config.security.userdetails.JwtUserDetails;
import com.strong.utils.mvc.pojo.view.ReplyVO;
import com.strong.utils.security.SecurityUtils;
import com.strong.utils.security.jwt.JwtResponseData;
import com.strong.utils.security.jwt.JwtTokenUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

import static com.strong.utils.security.SecurityUtils.MAP_SYSTEM_USER_AUTHENTICATION;
import static com.strong.utils.security.SecurityUtils.MAP_SYSTEM_USER_TOKEN;

/**
 * jwt认证成功处理程序
 *
 * @author simen
 * @date 2022/02/10
 */
@Slf4j
@Component("JwtAuthenticationSuccessHandler")
public class JwtAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Resource
    private JwtTokenUtils jwtTokenUtils;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        if (!response.isCommitted() && authentication != null && authentication.getPrincipal() != null
                // 获取登录用户信息对象
                && authentication.getPrincipal() instanceof JwtUserDetails userDetails) {

            // 获取30分钟有效的token编码
            String strToken = jwtTokenUtils.getToken30Minute(
                    userDetails.getUsername(),
                    CollUtil.join(userDetails.getAuthorities(), ","),
                    userDetails.getMapProperties()
            );

            // 更新系统缓存的用户JWT Token
            MAP_SYSTEM_USER_TOKEN.put(userDetails.getUsername(), strToken);
            // 删除系统缓存的用户身份验证对象
            MAP_SYSTEM_USER_AUTHENTICATION.remove(userDetails.getUsername());

            // 包装返回的JWT对象
            ReplyVO<JwtResponseData> replyVO = new ReplyVO<>(
                    new JwtResponseData(strToken, DateUtil.date()), "用户登录成功");

            // 将返回字符串写入response
            SecurityUtils.returnReplyJsonResponse(response, HttpServletResponse.SC_OK, replyVO);

            log.info("[{}]登录成功，已缓存该用户Token", userDetails.getUsername());
        }
    }
}
